import { IsNumber, IsBlank } from "../../../methods/judge";
import { RuleParse, CharHandle, RuleOptionalStack } from "../type";
import unicodeRuleParse from "./unicodeRuleParse";
import globelRuleParse from './globelRuleParse';

const JudgeIsBlank: CharHandle = (save, origin, rule, str, index, char, length) => IsBlank(char);
const JudgeNotBlank: CharHandle = (save, origin, rule, str, index, char, length) => !IsBlank(char);
const JudgeIsNumber: CharHandle = (save, origin, rule, str, index, char, length) => IsNumber(char);

const escapeRuleParse: RuleParse = {

	parseType: "escape",

	isNested: false,

	preHandle: (parse, rule, char) => { },

	judge: (parse, rule, char) => {
		if (char !== "\\") {
			return false;
		}
		parse.push(escapeRuleParse);
		return true;
	},

	// [canNested=true]
	handle: (parse, rule, char) => {
		const ruleO = rule as unknown as RuleOptionalStack;
		const parseType = parse.top && parse.top.parseType;
		if (parseType !== "escape") {
			return false;
		}
		if (char === "u") {
			ruleO.push({ ruleType: "equals", saveStr: "" });
			parse.pop();
			parse.push(unicodeRuleParse);
		} else {
			let ruleData: number | CharHandle;
			if (char === "d") { ruleData = JudgeIsNumber; }
			else if (char === "s") { ruleData = JudgeIsBlank; }
			else if (char === "S") { ruleData = JudgeNotBlank; }
			else { ruleData = char.charCodeAt(0); }
			if (typeof ruleData === "number") {
				ruleO.push({ ruleType: "equals", ruleData });
			} else {
				ruleO.push({ ruleType: "judge", ruleData });
			}
			parse.pop();
			const parseType = parse.top && parse.top.parseType;
			if (parseType !== "range") {
				parse.push(globelRuleParse);
			} else {
				ruleO.back();
			}
		}
		return true;
	},
};

export default escapeRuleParse;
